﻿using Blm.Utils.Extensions;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Core.Model.Ms;
using VisionCloud.Domain.DtoModel.Ms;
using VisionCloud.Domain.Repository.Interface.Ms;

namespace VisionCloud.Domain.Repository.Implement.Ms
{
    public class MsPointTypeRepository : BaseRepository<MsPointType>, IMsPointTypeRepository
    {
        /// <summary>
        /// 根据工艺阶段获取站点类型
        /// </summary>
        /// <returns></returns>
        public async Task<List<MsPointType>> GetList(bool hasDeleted)
        {
            return await (
                          from h in Db.MsPointTypes
                          where (hasDeleted || !h.IsDeleted)
                          select h).AsNoTracking().OrderBy(x => x.Type).ToListAsync();
        }

        public async Task<List<MsPointType>> GetListByProjectId(Guid projectGuid, bool hasDeleted = false)
        {
            return await (
                     from h in Db.MsPointTypes
                     where (!h.IsDeleted && h.ProjectGuid == projectGuid)
                     select h).AsNoTracking().OrderBy(x => x.Type).ToListAsync();
        }

        public async Task<List<MsPointType>> GetTemplateList()
        {
            return await (
                       from h in Db.MsPointTypes
                       where (!h.IsDeleted && h.ProjectGuid == new Guid())
                       select h).AsNoTracking().OrderBy(x => x.Type).ToListAsync();
        }

        public async Task<List<MsPointTypeDto>> GePointTypeDetail(Guid projectStandardId, Guid houseMapId, Guid PrjectGuid)
        {
            var points = new List<Guid>();
            if (houseMapId != Guid.Empty)
            {
                // 取户型图站点对应类型
                points = (
                              from h in Db.MsHouseMaps
                              join b in Db.MsHouseMapPoints on h.HouseMapId equals b.HouseMapId
                              where !h.IsDeleted && h.HouseMapId == houseMapId
                              select b.MsPointTypeId).Distinct().ToList();
            }

            List<MsPointTypeDto> result = null;
            // 取所有站点类型
            result = await (
                          from h in Db.MsPointTypes
                          where !h.IsDeleted && (points.Count == 0 || points.Contains(h.Id)) && h.ProjectGuid == PrjectGuid
                          orderby h.Type ascending
                          select new MsPointTypeDto()
                          {
                              Id = h.Id,
                              Name = h.Name,
                              Type = (int)h.Type,
                              ProjectGuid = h.ProjectGuid,
                              MsPointTypeId = h.MsPointTypeId,
                              CompanyGuid = h.CompanyGuid
                              //MeasureItemId = a.Id
                          }).AsNoTracking().ToListAsync().ConfigureAwait(false);

            if (result.IsEmpty())
            {
                return new List<MsPointTypeDto>();
            }

            // 根据阶段获取站点类型下的测量项
            var measureItems = await (from a in Db.MsPointTypeMeasureItems
                                      join b in Db.MsProjectStandardMeasureItems
                                      on new
                                      {
                                          projectGuid = a.ProjectGuid,
                                          id = a.Id
                                      } equals new
                                      {
                                          projectGuid = b.ProjectGuid,
                                          id = b.Id
                                      }
                                      where b.Type == 1 && a.ProjectStandardId == projectStandardId && a.ProjectGuid == PrjectGuid &&
                                      result.Select(r => r.Id).Contains(a.MsPointTypeId)
                                      orderby b.Code, b.Title ascending
                                      select new MsPointTypeItemDto()
                                      {
                                          MeasureItemId = a.Id,
                                          IsChecked = a.IsChecked,
                                          Title = b.Title,
                                          Code = b.Code,
                                          SupportCraft = b.SupportCraft,
                                          SupportStandard = b.SupportStandard,
                                          Type = b.Type,
                                          HasDesignValue = b.HasDesignValue,
                                          ProjectStandardId = a.ProjectStandardId,
                                          CompanyGuid = a.CompanyGuid,
                                          MsPointTypeId = a.MsPointTypeId,
                                          ProjectGuid = a.ProjectGuid,
                                          MsPointTypeMeasureItemId = a.MsPointTypeMeasureItemId
                                      }).AsNoTracking().ToListAsync().ConfigureAwait(false);

            result.ForEach(x =>
            {
                x.MeasureItem = measureItems.Where(y => y.MsPointTypeId == x.Id).ToList();
            });

            return result;
        }

        /// <summary>
        /// 取最大的类型序号
        /// </summary>
        /// <returns></returns>
        public async Task<int> GetMaxType(Guid projectGuid)
        {
            var result = await (
              from h in Db.MsPointTypes
              where !h.IsDeleted && h.ProjectGuid == projectGuid
              select h).AsNoTracking().OrderByDescending(x => x.Type).FirstOrDefaultAsync().ConfigureAwait(false);
            if (result == null)
            {
                return 1;
            }
            return (int)result.Type + 1;
        }

        public async Task<MsPointType> GetPointType(string name, Guid projectGuid)
        {
            return await Db.MsPointTypes.FirstOrDefaultAsync(x => x.ProjectGuid == projectGuid && x.Name.ToLower() == name.ToLower())
                                        .ConfigureAwait(false);
        }

        /// <summary>
        /// 获取任务的标准库测量项数据
        /// </summary>
        /// <param name="projectStandardId"></param>
        /// <param name="taskId"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public async Task<List<MsPointTypeDto>> GetTaskStandards(Guid projectStandardId, Guid taskId, Guid projectId)
        {
            // 取所有站点类型  
            var result = await (
                          from h in Db.MsPointTypes
                          join p in Db.MsTaskStandards on h.Id equals p.MsPointTypeId
                          //where !h.IsDeleted  
                          where h.ProjectGuid == projectId
                          orderby h.Type ascending
                          select new MsPointTypeDto()
                          {
                              Id = h.Id,
                              Name = h.Name,
                              Type = h.Type,
                              CompanyGuid = h.CompanyGuid,
                              MsPointTypeId = h.MsPointTypeId,
                              ProjectGuid = h.ProjectGuid,
                              ProjectStandardId = projectStandardId
                          }).AsNoTracking().Distinct().ToListAsync();

            if (result == null || result.Count == 0)
            {
                return new List<MsPointTypeDto>();
            }

            // 获取MsPointTypeId的集合  
            var pointTypeIds = result.Select(r => r.Id).ToList();

            // 一次性获取所有相关的测量项  
            var allMeasureItems = await (from h in Db.MsTaskStandards
                                         where h.TaskId == taskId && h.Type == 1 && pointTypeIds.Contains(h.MsPointTypeId)
                                         orderby h.Code, h.Title ascending
                                         select new MsPointTypeItemDto()
                                         {
                                             MsPointTypeId = h.MsPointTypeId,
                                             MeasureItemId = h.Id,
                                             IsChecked = h.IsChecked,
                                             Title = h.Title,
                                             Code = h.Code,
                                             SupportCraft = h.SupportCraft,
                                             SupportStandard = h.SupportStandard,
                                             Type = h.Type,
                                             HasDesignValue = h.HasDesignValue,
                                             ProjectStandardId = h.ProjectStandardId,
                                             ProjectGuid = projectId
                                         }).AsNoTracking().ToListAsync();

            // 根据阶段获取站点类型下的测量项副本  
            foreach (var item in result)
            {
                item.MeasureItem = allMeasureItems.Where(h => h.MsPointTypeId == item.Id).ToList();
                item.MeasureItem?.ForEach(h => 
                {
                    h.CompanyGuid = item.CompanyGuid;
                });
            }

            return result.Where(x => x.MeasureItem.IsNotEmpty()).ToList();
        }

        public async Task<List<MeasurePoints>> GetTaskPointsByType(Guid typeId, Guid projectid)
        {
            var result = await (from p in Db.MsTasks
                                join h in Db.TaskPointss on p.TaskId equals h.TaskId
                                join u in Db.MsPointTypes on new { pointTypeID = h.MsPointTypeId, projectid = p.ProjectId }
                                equals new
                                {
                                    pointTypeID = u.Id,
                                    projectid = u.ProjectGuid
                                }
                                where u.Id == typeId && !p.IsDeleted && !h.IsDeleted && p.ProjectId == projectid
                                orderby h.pintIndex ascending
                                select new MeasurePoints
                                {
                                    PointId = h.pointId,
                                    pointIndex = h.pintIndex,
                                    x = h.x,
                                    y = h.y,
                                    offsetX = h.offsetX,
                                    offsetY = h.offsetY,
                                    Type = u.Type,
                                    TypeId = u.Id,
                                    TypeName = u.Name,
                                }).AsNoTracking().OrderBy(x => x.pointIndex).ToListAsync().ConfigureAwait(false);

            return result;
        }

        public async Task<List<MsPointType>> GetDataByProjects(Guid[] projectIds)
        {
            return await (
                         from h in Db.MsPointTypes
                         where projectIds.Contains(h.ProjectGuid)
                         select h).AsNoTracking().ToListAsync().ConfigureAwait(false);
        }
    }
}